package org.carabiner.infinitest.swingui;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import javax.swing.SwingUtilities;

import org.carabiner.infinitest.TestEvent;
import org.carabiner.infinitest.TestStatusListener;

public class EventSupport
{
  private EventSupport()
  {
  }

  /**
   * Ensures that test events are dispatched on the event thread
   */
  public static TestStatusListener eventNormalizer(final TestStatusListener listener)
  {
    return (TestStatusListener) Proxy.newProxyInstance(listener.getClass().getClassLoader(), new Class[] { TestStatusListener.class }, new InvocationHandler()
    {
      public Object invoke(Object proxy, final Method method, final Object[] args) throws Throwable
      {
        runThisOnEventThread(new Runnable()
        {
          public void run()
          {
            try
            {
              method.invoke(listener, args);
            }
            catch (IllegalAccessException e)
            {
              throw new RuntimeException(e);
            }
            catch (InvocationTargetException e)
            {
              throw new RuntimeException(e);
            }
          }
        });
        return null;
      }
    });
  }

  public static void runThisOnEventThread(Runnable runnable)
  {
    if (!SwingUtilities.isEventDispatchThread())
    {
      try
      {
        SwingUtilities.invokeAndWait(runnable);
      }
      catch (InterruptedException e)
      {
        throw new RuntimeException(e);
      }
      catch (InvocationTargetException e)
      {
        throw new RuntimeException(e);
      }
    }
    else
      runnable.run();
  }
}
